#ifndef ALFS_STDX_TYPE_TRAITS_HPP
#define ALFS_STDX_TYPE_TRAITS_HPP
#include    <alfs/config.hpp>

// File [alfs/stdx/type_traits.hpp].
//
// (c) copyright Alf P. Steinbach 2008.
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php>.
//
// Implements C++0x <type_traits> header by
// placing TR1 stuff in namespace "std" for pre-C++0x compilers.
// TR1 is the standard library additions planned for C++0x.
// "using" directives generated by search+replace on Boost TR1 implementation.

#if ALFS_IS_CPP0X_OR_LATER
#   include     <type_traits>
#   include     <alfs/language_support/Bool3Enum.hpp>

    // For forward-compatibility (these are the tricky ones not supported by all compilers).
    //
    // For not-yet-C++0x compilers these are instead defined by modified version of
    // <boost/type_traits/intrinsics.hpp>, where in the middle of that file included
    // <alfs/language_support/detail/extension_of_boost_type_traits_intrinsics.hpp>.
    namespace alfs{

        template< typename T > struct IsUnion
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::is_union<T>::value>::value;
        };
 
        template< typename T > struct IsPOD
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::is_pod<T>::value>::value;
        };

        template< typename T > struct IsEmpty
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::is_empty<T>::value>::value;
        };

        template< typename T > struct HasTrivialConstructor
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_trivial_constructor<T>::value>::value;
        };

        template< typename T > struct HasTrivialCopy
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::is_trivial_copy<T>::value>::value;
        };

        template< typename T > struct HasTrivialAssign
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::is_trivial_assign<T>::value>::value;
        };

        template< typename T > struct HasTrivialDestructor
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_trivial_destructor<T>::value>::value;
        };

        template< typename T > struct HasNothrowConstructor
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_nothrow_constructor<T>::value>::value;
        };

        template< typename T > struct HasNothrowCopy
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_nothrow_copy<T>::value>::value;
        };

        template< typename T > struct HasNothrowAssign
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_nothrow_assign<T>::value>::value;
        };

        template< typename T > struct HasVirtualDestructor
        {
            static Bool3::Enum const value =
                Bool3::FromBool<std::has_virtual_destructor<T>::value>::value;
        };

    }  // alfs

#else
#   include <boost/tr1/type_traits.hpp>  // Note: patch brings in definitions corresponding to above.
#
#   ifndef   BOOST_TT_INTRINSICS_HPP_INCLUDED
#       error <boost/tr1/type_traits.hpp> did not bring in <boost/type_traits/intrinsics.hpp>.
#   endif
#
#   if defined(ALFS_USE_BOOST_TYPETRAITS_INTRINSICS_PATCH) && !defined(ALFS_BOOST_TYPETRAITS_INTRINSICS_PATCH)
#       error <boost/type_traits/intrinsics.hpp> is not patched: patch or define ALFS_DONT_USE_BOOST_TYPETRAITS_INTRINSICS_PATCH
#       // See file <alfs/language_support/detail/extension_of_boost_type_traits_intrinsics.hpp>.
#   endif

    namespace std{
        using ::std::tr1::integral_constant;
        using ::std::tr1::true_type;
        using ::std::tr1::false_type;
        using ::std::tr1::is_void;
        using ::std::tr1::is_integral;
        using ::std::tr1::is_floating_point;
        using ::std::tr1::is_array;
        using ::std::tr1::is_pointer;
        using ::std::tr1::is_reference;
        using ::std::tr1::is_member_object_pointer;
        using ::std::tr1::is_member_function_pointer;
        using ::std::tr1::is_enum;
        using ::std::tr1::is_union;
        using ::std::tr1::is_class;
        using ::std::tr1::is_function;
        using ::std::tr1::is_arithmetic;
        using ::std::tr1::is_fundamental;
        using ::std::tr1::is_object;
        using ::std::tr1::is_scalar;
        using ::std::tr1::is_compound;
        using ::std::tr1::is_member_pointer;
        using ::std::tr1::is_const;
        using ::std::tr1::is_volatile;
        using ::std::tr1::is_pod;
        using ::std::tr1::is_empty;
        using ::std::tr1::is_polymorphic;
        using ::std::tr1::is_abstract;
        using ::std::tr1::has_trivial_constructor;
        using ::std::tr1::has_trivial_copy;
        using ::std::tr1::has_trivial_assign;
        using ::std::tr1::has_trivial_destructor;
        using ::std::tr1::has_nothrow_constructor;
        using ::std::tr1::has_nothrow_copy;
        using ::std::tr1::has_nothrow_assign;
        using ::std::tr1::has_virtual_destructor;
        using ::std::tr1::is_signed;
        using ::std::tr1::is_unsigned;
        using ::std::tr1::alignment_of;
        using ::std::tr1::rank;
        using ::std::tr1::extent;
        using ::std::tr1::is_same;
        using ::std::tr1::is_base_of;
        using ::std::tr1::is_convertible;
        using ::std::tr1::remove_const;
        using ::std::tr1::remove_volatile;
        using ::std::tr1::remove_cv;
        using ::std::tr1::add_const;
        using ::std::tr1::add_volatile;
        using ::std::tr1::add_cv;
        using ::std::tr1::remove_reference;
        using ::std::tr1::add_reference;
        using ::std::tr1::remove_extent;
        using ::std::tr1::remove_all_extents;
        using ::std::tr1::remove_pointer;
        using ::std::tr1::add_pointer;
        using ::std::tr1::aligned_storage;
    }  // std
#endif

namespace alfs{

    template< typename Derived, typename Base >
    struct IsDerivedAndBase: std::is_base_of<Base, Derived>
    { enum { yes = std::is_base_of<Base, Derived>::value }; };

    template< typename From, typename To >
    struct IsConvertibleFromTo: std::is_convertible<From, To>
    { enum { yes = std::is_convertible<From, To>::value }; };

}  // alfs

#endif
